from nicegui import ui

from ..documentation_tools import text_demo


def main_demo() -> None:
    columns = [
        {'name': 'name', 'label': 'Name', 'field': 'name', 'required': True, 'align': 'left'},
        {'name': 'age', 'label': 'Age', 'field': 'age', 'sortable': True},
    ]
    rows = [
        {'name': 'Alice', 'age': 18},
        {'name': 'Bob', 'age': 21},
        {'name': 'Carol'},
    ]
    ui.table(columns=columns, rows=rows, row_key='name')


def more() -> None:
    @text_demo('Table with expandable rows', '''
        Scoped slots can be used to insert buttons that toggle the expand state of a table row.
        See the [Quasar documentation](https://quasar.dev/vue-components/table#expanding-rows) for more information.
    ''')
    def table_with_expandable_rows():
        columns = [
            {'name': 'name', 'label': 'Name', 'field': 'name'},
            {'name': 'age', 'label': 'Age', 'field': 'age'},
        ]
        rows = [
            {'name': 'Alice', 'age': 18},
            {'name': 'Bob', 'age': 21},
            {'name': 'Carol'},
        ]

        table = ui.table(columns=columns, rows=rows, row_key='name').classes('w-72')
        table.add_slot('header', r'''
            <q-tr :props="props">
                <q-th auto-width />
                <q-th v-for="col in props.cols" :key="col.name" :props="props">
                    {{ col.label }}
                </q-th>
            </q-tr>
        ''')
        table.add_slot('body', r'''
            <q-tr :props="props">
                <q-td auto-width>
                    <q-btn size="sm" color="accent" round dense
                        @click="props.expand = !props.expand"
                        :icon="props.expand ? 'remove' : 'add'" />
                </q-td>
                <q-td v-for="col in props.cols" :key="col.name" :props="props">
                    {{ col.value }}
                </q-td>
            </q-tr>
            <q-tr v-show="props.expand" :props="props">
                <q-td colspan="100%">
                    <div class="text-left">This is {{ props.row.name }}.</div>
                </q-td>
            </q-tr>
        ''')

    @text_demo('Show and hide columns', '''
        Here is an example of how to show and hide columns in a table.
    ''')
    def show_and_hide_columns():
        from typing import Dict

        columns = [
            {'name': 'name', 'label': 'Name', 'field': 'name', 'required': True, 'align': 'left'},
            {'name': 'age', 'label': 'Age', 'field': 'age', 'sortable': True},
        ]
        rows = [
            {'name': 'Alice', 'age': 18},
            {'name': 'Bob', 'age': 21},
            {'name': 'Carol'},
        ]
        table = ui.table(columns=columns, rows=rows, row_key='name')

        def toggle(column: Dict, visible: bool) -> None:
            column['classes'] = '' if visible else 'hidden'
            column['headerClasses'] = '' if visible else 'hidden'
            table.update()

        with ui.button(icon='menu'):
            with ui.menu(), ui.column().classes('gap-0 p-2'):
                for column in columns:
                    ui.switch(column['label'], value=True, on_change=lambda e, column=column: toggle(column, e.value))

    @text_demo('Table with drop down selection', '''
        Here is an example of how to use a drop down selection in a table.
        After emitting a `rename` event from the scoped slot, the `rename` function updates the table rows.
    ''')
    def table_with_drop_down_selection():
        from nicegui import events

        columns = [
            {'name': 'name', 'label': 'Name', 'field': 'name'},
            {'name': 'age', 'label': 'Age', 'field': 'age'},
        ]
        rows = [
            {'id': 0, 'name': 'Alice', 'age': 18},
            {'id': 1, 'name': 'Bob', 'age': 21},
            {'id': 2, 'name': 'Carol'},
        ]
        name_options = ['Alice', 'Bob', 'Carol']

        def rename(e: events.GenericEventArguments) -> None:
            for row in rows:
                if row['id'] == e.args['id']:
                    row['name'] = e.args['name']
            ui.notify(f'Table.rows is now: {table.rows}')

        table = ui.table(columns=columns, rows=rows, row_key='name').classes('w-full')
        table.add_slot('body', r'''
            <q-tr :props="props">
                <q-td key="name" :props="props">
                    <q-select
                        v-model="props.row.name"
                        :options="''' + str(name_options) + r'''"
                        @update:model-value="() => $parent.$emit('rename', props.row)"
                    />
                </q-td>
                <q-td key="age" :props="props">
                    {{ props.row.age }}
                </q-td>
            </q-tr>
        ''')
        table.on('rename', rename)

    @text_demo('Table from Pandas DataFrame', '''
        You can create a table from a Pandas DataFrame using the `from_pandas` method. 
        This method takes a Pandas DataFrame as input and returns a table.
    ''')
    def table_from_pandas_demo():
        import pandas as pd

        df = pd.DataFrame(data={'col1': [1, 2], 'col2': [3, 4]})
        ui.table.from_pandas(df).classes('max-h-40')

    @text_demo('Adding rows', '''
        It's simple to add new rows with the `add_rows(dict)` method.
    ''')
    def adding_rows():
        import os
        import random

        def add():
            item = os.urandom(10 // 2).hex()
            table.add_rows({'id': item, 'count': random.randint(0, 100)})

        ui.button('add', on_click=add)
        columns = [
            {'name': 'id', 'label': 'ID', 'field': 'id'},
            {'name': 'count', 'label': 'Count', 'field': 'count'},
        ]
        table = ui.table(columns=columns, rows=[], row_key='id').classes('w-full')

    @text_demo('Custom sorting and formatting', '''
        You can define dynamic column attributes using a `:` prefix.
        This way you can define custom sorting and formatting functions.

        The following example allows sorting the `name` column by length.
        The `age` column is formatted to show the age in years.
    ''')
    def custom_formatting():
        columns = [
            {
                'name': 'name',
                'label': 'Name',
                'field': 'name',
                'sortable': True,
                ':sort': '(a, b, rowA, rowB) => b.length - a.length',
            },
            {
                'name': 'age',
                'label': 'Age',
                'field': 'age',
                ':format': 'value => value + " years"',
            },
        ]
        rows = [
            {'name': 'Alice', 'age': 18},
            {'name': 'Bob', 'age': 21},
            {'name': 'Carl', 'age': 42},
        ]
        ui.table(columns=columns, rows=rows, row_key='name')

    @text_demo('Toggle fullscreen', '''
        You can toggle the fullscreen mode of a table using the `toggle_fullscreen()` method.
    ''')
    def toggle_fullscreen():
        table = ui.table(
            columns=[{'name': 'name', 'label': 'Name', 'field': 'name'}],
            rows=[{'name': 'Alice'}, {'name': 'Bob'}, {'name': 'Carol'}],
        ).classes('w-full')

        with table.add_slot('top-left'):
            def toggle() -> None:
                table.toggle_fullscreen()
                button.props('icon=fullscreen_exit' if table.is_fullscreen else 'icon=fullscreen')
            button = ui.button('Toggle fullscreen', icon='fullscreen', on_click=toggle).props('flat')

    @text_demo('Pagination', '''
        You can provide either a single integer or a dictionary to define pagination.

        The dictionary can contain the following keys:

        - `rowsPerPage`: The number of rows per page.
        - `sortBy`: The column name to sort by.
        - `descending`: Whether to sort in descending order.
        - `page`: The current page (1-based).
    ''')
    def pagination() -> None:
        columns = [
            {'name': 'name', 'label': 'Name', 'field': 'name', 'required': True, 'align': 'left'},
            {'name': 'age', 'label': 'Age', 'field': 'age', 'sortable': True},
        ]
        rows = [
            {'name': 'Elsa', 'age': 18},
            {'name': 'Oaken', 'age': 46},
            {'name': 'Hans', 'age': 20},
            {'name': 'Sven'},
            {'name': 'Olaf', 'age': 4},
            {'name': 'Anna', 'age': 17},
        ]
        ui.table(columns=columns, rows=rows, pagination=3)
        ui.table(columns=columns, rows=rows, pagination={'rowsPerPage': 4, 'sortBy': 'age', 'page': 2})

    @text_demo('Computed fields', '''
        You can use functions to compute the value of a column.
        The function receives the row as an argument.
        See the [Quasar documentation](https://quasar.dev/vue-components/table#defining-the-columns) for more information.
    ''')
    def computed_fields():
        columns = [
            {'name': 'name', 'label': 'Name', 'field': 'name', 'align': 'left'},
            {'name': 'length', 'label': 'Length', ':field': 'row => row.name.length'},
        ]
        rows = [
            {'name': 'Alice'},
            {'name': 'Bob'},
            {'name': 'Christopher'},
        ]
        ui.table(columns=columns, rows=rows, row_key='name')

    @text_demo('Conditional formatting', '''
        You can use scoped slots to conditionally format the content of a cell.
        See the [Quasar documentation](https://quasar.dev/vue-components/table#example--body-cell-slot)
        for more information about body-cell slots.
        
        In this demo we use a `q-badge` to display the age in red if the person is under 21 years old.
        We use the `body-cell-age` slot to insert the `q-badge` into the `age` column.
        The ":color" attribute of the `q-badge` is set to "red" if the age is under 21, otherwise it is set to "green".
        The colon in front of the "color" attribute indicates that the value is a JavaScript expression.
    ''')
    def conditional_formatting():
        columns = [
            {'name': 'name', 'label': 'Name', 'field': 'name'},
            {'name': 'age', 'label': 'Age', 'field': 'age'},
        ]
        rows = [
            {'name': 'Alice', 'age': 18},
            {'name': 'Bob', 'age': 21},
            {'name': 'Carol', 'age': 42},
        ]
        table = ui.table(columns=columns, rows=rows, row_key='name')
        table.add_slot('body-cell-age', '''
            <q-td key="age" :props="props">
                <q-badge :color="props.value < 21 ? 'red' : 'green'">
                    {{ props.value }}
                </q-badge>
            </q-td>
        ''')

    @text_demo('Table cells with links', '''
        Here is a demo of how to insert links into table cells.
        We use the `body-cell-link` slot to insert an `<a>` tag into the `link` column.
    ''')
    def table_cells_with_links():
        columns = [
            {'name': 'name', 'label': 'Name', 'field': 'name', 'align': 'left'},
            {'name': 'link', 'label': 'Link', 'field': 'link', 'align': 'left'},
        ]
        rows = [
            {'name': 'Google', 'link': 'https://google.com'},
            {'name': 'Facebook', 'link': 'https://facebook.com'},
            {'name': 'Twitter', 'link': 'https://twitter.com'},
        ]
        table = ui.table(columns=columns, rows=rows, row_key='name')
        table.add_slot('body-cell-link', '''
            <q-td :props="props">
                <a :href="props.value">{{ props.value }}</a>
            </q-td>
        ''')
